﻿using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using metroioc;

namespace MetroIoc.Tests
{
    [TestClass]
    public class LifecycleTests
    {
        [TestMethod]
        public void ResolveCreatesInstancePerRequest()
        {
            var iocContainer = new MetroContainer()
                .Register<IFoo, Foo>();

            var instance1 = iocContainer.Resolve<IFoo>();
            var instance2 = iocContainer.Resolve<IFoo>();

            Assert.AreNotSame(instance1, instance2);
        }

        [TestMethod]
        public void ResolveCreatesSingletonIfSpecified()
        {
            var iocContainer = new MetroContainer()
                .Register<IFoo, Foo>(registration: new Singleton());

            var instance1 = iocContainer.Resolve<IFoo>();
            var instance2 = iocContainer.Resolve<IFoo>();

            Assert.AreSame(instance1, instance2);
        }


        [TestMethod]
        public void RegisterSingletonDoesNotResolveInstance()
        {
            var threw = false;
            try
            {
                var container = new MetroContainer()
                    .Register<Bar>(registration: new Singleton());
            }
            catch (ResolutionException)
            {
                threw = true;
            }
            finally
            {
                Assert.IsFalse(threw, "Register should not have thrown ResolutionException");
            }
        }

        [TestMethod]
        public void RegisterSingletonThrowsWhenResolvedIfDependencyNotRegistered()
        {
            var container = new MetroContainer()
                .Register<Bar>(registration: new Singleton());

            // Do not register dependency IFoo...
            Assert.ThrowsException<ResolutionException>(
                () => container.Resolve<Bar>());
        }


        [TestMethod]
        public void RegisterInstanceRegistersAsSingleton()
        {
            var instance = new Bar(new Foo());

            var container = new MetroContainer()
                .RegisterInstance<Bar>(instance);

            var b1 = container.Resolve<Bar>();
            var b2 = container.Resolve<Bar>();

            Assert.AreSame(instance, b1);
            Assert.AreSame(instance, b2);
        }


        interface IFoo { }
        class Foo : IFoo { }

        class Bar 
        {
            private readonly IFoo _foo;

            public Bar(IFoo foo)
            {
                _foo = foo;
            }
        }

    }
}
